//package com.hjqjl.ftp;
//
//import android.os.Environment;
//import android.os.SystemClock;
//
//import com.aill.androidserialport.SerialPort;
//import com.blankj.utilcode.util.ArrayUtils;
//import com.blankj.utilcode.util.ConvertUtils;
//import com.blankj.utilcode.util.FileIOUtils;
//import com.blankj.utilcode.util.FileUtils;
//import com.blankj.utilcode.util.LogUtils;
//import com.blankj.utilcode.util.StringUtils;
//import com.blankj.utilcode.util.ToastUtils;
//import com.google.gson.Gson;
//
//import org.apache.commons.net.ftp.FTPClient;
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.IOException;
//import java.io.InputStream;
//import java.io.OutputStream;
//import java.nio.MappedByteBuffer;
//import java.nio.channels.FileChannel;
//import java.nio.charset.Charset;
//
//public class WineTestUpdateUtils {
//    private static WineTestUpdateUtils instance;
//    private SerialPort mSerialPort;
//    private OutputStream out;
//    private InputStream mInputStream;
//
//    private WineTestUpdateUtils() {// 单例模式中获取唯一的实例
//        try {
//            mSerialPort = new SerialPort(new File("/dev/ttyS3"), 115200, 0);
//            out = mSerialPort.getOutputStream();
//            mInputStream = mSerialPort.getInputStream();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    public static WineTestUpdateUtils getInstance() {
//        if (null == instance) {
//            instance = new WineTestUpdateUtils();
//        }
//        return instance;
//    }
//
//    private final static String CFGPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/CFG";//酒精测试配置存储的位置
//    private final static String CFG_AD_UPDATE_PATH = CFGPath + "/ad_update";//酒精测试固件包存储的位置
//    private static final String ip = "203.156.246.17";
//    private static final int port = 8421;
//    private static final String userName = "ftp2";
//    private static final String password = "123456ftp2";
//    private static final String ftpDir = "/ad_update/";
//    private String fTPfilename = "";
//
//    /**
//     * 酒测时间校准
//     */
//    public void timeCalibration() {
//        try {
//            long stamp = System.currentTimeMillis() / 1000;
//            LogUtils.v("当前时间(unix时间戳 s)" + stamp);
//            byte[] b = ByteTool.long2bytes(stamp, 4);
//            byte sum = (byte) (0x04 + 0x05 + b[3] + b[2] + b[1] + b[0]);
//            byte[] otuBytes = new byte[]{(byte) 0xA5, 0x5A, 0x04, 0x00, 0x05, b[3], b[2], b[1], b[0], sum, (byte) 0xAA, 0x55};
//            // 写入数据
//            try {
//                LogUtils.v("酒测时间校准", ConvertUtils.bytes2HexString(otuBytes));
//                out.write(otuBytes);
//                out.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SystemClock.sleep(50);
//
//            //---------将串口中的数 据读出来丢掉 start------------//
//            long time = System.currentTimeMillis() + 2000;
//            int read_count = mInputStream.available();
//            while (read_count == 0) {
//                SystemClock.sleep(50);
//                read_count = mInputStream.available();
//                long currentTime = System.currentTimeMillis();
//                if (currentTime > time) {
//                    return;//超时--可能设备没有连接好
//                }
//            }
//            byte[] read_info = new byte[read_count];
//            mInputStream.read(read_info, 0, read_count);
//            LogUtils.v("酒测时间校准返回", ConvertUtils.bytes2HexString(read_info));
//            //---------将串口中遗留的数 据读出来丢掉 end------------//
//
//        } catch (Exception e) {
//            if (mSerialPort != null) {
//                mSerialPort.close();
//            }
//        }
//    }
//
//    /**
//     * 获取酒测版本信息
//     *
//     * @param isUpdate 是否更新
//     * @return 版本号
//     */
//    public String getAlcoholVersion(boolean isUpdate) {
//        try {
//            //---------将串口中的数 据读出来丢掉 start------------//
//            mInputStream = mSerialPort.getInputStream();
//            int read_count1 = mInputStream.available();
//            byte[] read_info = new byte[read_count1];
//            mInputStream.read(read_info, 0, read_count1);
//            LogUtils.v("丢弃数据返回", ConvertUtils.bytes2HexString(read_info));
//            //---------将串口中遗留的数 据读出来丢掉 end------------//
//
//            byte sum = (byte) 0x06;
//            byte[] otuBytes = new byte[]{(byte) 0xA5, 0x5A, 0x00, 0x00, 0x06, sum, (byte) 0xAA, 0x55};
//            // 写入数据
//            try {
//                LogUtils.v("获取酒测版本信息", ConvertUtils.bytes2HexString(otuBytes));
//                out.write(otuBytes);
//                out.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SystemClock.sleep(50);
//
//            long time = System.currentTimeMillis() + 2000;
//            int read_count = mInputStream.available();
//            while (read_count == 0) {
//                SystemClock.sleep(50);
//                read_count = mInputStream.available();
//                LogUtils.v(read_count);
//                long currentTime = System.currentTimeMillis();
//                if (currentTime > time) {
//                    return "";//超时--可能设备没有连接好
//                }
//            }
//            byte[] buffer = new byte[read_count];
//            mInputStream.read(buffer, 0, read_count);
//
//            LogUtils.v("获取版本信息结果返回", ConvertUtils.bytes2HexString(buffer));
//
//            if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x06) {
//                //02年+02月+02日+02小版本+下划线+补充说明  例：22012101_SRC_APP
//                byte[] verLengthBytes = new byte[]{buffer[3], buffer[2]};
//                int verLength = ConvertUtils.hexString2Int(ConvertUtils.bytes2HexString(verLengthBytes)) - 1;
//                byte[] verBytes = new byte[verLength];
//                if (verLength >= 0) {
//                    System.arraycopy(buffer, 5, verBytes, 0, verLength);
//                }
//                String ver = ConvertUtils.bytes2String(verBytes);//格式 例：21120801_SRC_BOOT 或 22012101_SRC_APP
//                if (ver.length() >= 8) {
//                    if (isUpdate) {
//                        String version = ver.substring(0, 8);
//                        LogUtils.v(version);
//                        updateCFG(version);
//                    }
//                    return ver;
//                } else {
//                    return "";
//                }
//            } else if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x10) {
//                toastErrMsg(buffer, "获取版本信息错误");
//                return "";
//            } else {
//                return "";
//            }
//        } catch (Exception e) {
//            if (mSerialPort != null) {
//                mSerialPort.close();
//            }
//            return "";
//        }
//    }
//
//    /**
//     * 下载json文件(内有版本信息)
//     */
//    private void updateCFG(String version) {
//        String fileName = "CFG.json";
//        try {
//            FtpUtils ftpUtils = new FtpUtils();
//            FTPClient ftpClient = ftpUtils.getFTPClient(ip, port, userName, password);
//
//            if (ftpClient != null) {
//                boolean isDown = ftpUtils.downLoadFTP(ftpClient, ftpDir, fileName, CFGPath);
//                ftpUtils.closeFTP(ftpClient);
//                if (isDown) {
//                    readFile(fileName, version);
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 读取json信息里的版本信息
//     */
//    private void readFile(String fileName, String version) {
//        try {
//            File yourFile = new File(CFGPath + File.separator + fileName);
//            if (!yourFile.exists()) {
//                return;
//            }
//            FileInputStream stream = new FileInputStream(yourFile);
//            String jsonStr = null;
//            try {
//                FileChannel fc = stream.getChannel();
//                MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
//                jsonStr = Charset.defaultCharset().decode(bb).toString();
//            } catch (Exception e) {
//                e.printStackTrace();
//            } finally {
//                stream.close();
//            }
//
//            CFGModel cfgModel = new Gson().fromJson(jsonStr, CFGModel.class);
//            LogUtils.v(cfgModel.getFTPfiledir() + "---" + cfgModel.getFTPfilename()
//                    + "---" + cfgModel.getMD5() + "---" + cfgModel.getVer());
//            fTPfilename = cfgModel.getFTPfilename();
//
//            //这里要判断需不需要升级
//            try {
//                int onLineVer = Integer.parseInt(cfgModel.getVer());
//                int localVer = Integer.parseInt(version);
//                LogUtils.v(onLineVer + "--" + localVer);
//                if (onLineVer > localVer) {//如果线上版本号大于本地版本号，则进行升级
//                    AlcoholDetect_APP(cfgModel);
//                } else {
//                    timeCalibration();
//                }
//            } catch (Exception ignored) {
//
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 下载固件升级包（.bin格式文件）
//     */
//    private void AlcoholDetect_APP(CFGModel cfgModel) {
//        try {
//            FtpUtils ftpUtils = new FtpUtils();
//            FTPClient ftpClient = ftpUtils.getFTPClient(ip, port, userName, password);
//            try {
//                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//设置传输类型为二进制流，不然文件有损坏
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            if (ftpClient != null) {
//                ftpUtils.downLoadFTP(ftpClient, cfgModel.getFTPfiledir(), cfgModel.getFTPfilename(), CFG_AD_UPDATE_PATH);
//                ftpUtils.closeFTP(ftpClient);
//            }
//
//            String fileMd5 = FileUtils.getFileMD5ToString(CFG_AD_UPDATE_PATH + File.separator + fTPfilename);
//            LogUtils.v(fileMd5);
//            if (StringUtils.equalsIgnoreCase(fileMd5, cfgModel.getMD5())) {//保证下载的文件没损坏
//                long time = System.currentTimeMillis() + 30000;
//                updateFirmwarePrepare(time);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 程序升级准备命令
//     * 有点奇葩不要动，程序中要一直不停的发消息直到收到返回信息（固件同学这样设定的）
//     */
//    private void updateFirmwarePrepare(long time) {
//        try {
//            //*转化为字节为0x2A
//            byte sum = (byte) (0x06 + (byte) 0xFF + 0x2A + 0x2A + 0x2A + 0x2A + 0x2A + 0x2A);
//            //******即0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A
//            byte[] otuBytes = new byte[]{(byte) 0xA5, 0x5A, 0x06, 0x00, (byte) 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
//                    sum, (byte) 0xAA, 0x55};
//            // 写入数据
//            try {
//                LogUtils.v("程序升级准备命令", ConvertUtils.bytes2HexString(otuBytes));
//                out.write(otuBytes);
//                out.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SystemClock.sleep(100);//时间不能太长，测试100ms正合适
//
//            long currentTime = System.currentTimeMillis();
//            if (currentTime > time) {
//                return;//超时--可能设备没有连接好
//            }
//
//            int read_count = mInputStream.available();
//
//            if (read_count == 0) {//要一直不停的发消息直到收到返回信息（固件同学这样设定的）
//                updateFirmwarePrepare(time);
//                return;
//            }
//            byte[] buffer = new byte[read_count];
//            mInputStream.read(buffer, 0, read_count);
//            LogUtils.v("程序升级准备命令返回", ConvertUtils.bytes2HexString(buffer));
//
//            if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == (byte) 0xFF) {  //验证码
//                //#转化为字节为0x23
//                if (buffer[5] == 0x23 && buffer[6] == 0x23
//                        && buffer[7] == 0x23 && buffer[8] == 0x23
//                        && buffer[9] == 0x23 && buffer[10] == 0x23) {//即为######，进行程序升级
//                    LogUtils.v("******");
//                    updateFirmwareInfo();
//                }
//            } else if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x10) {
//                toastErrMsg(buffer, "程序升级准备命令错误");
//            }
//        } catch (Exception e) {
//            if (mSerialPort != null) {
//                mSerialPort.close();
//            }
//        }
//    }
//
//    /**
//     * 程序信息
//     */
//    private void updateFirmwareInfo() {
//        try {
//            File file = FileUtils.getFileByPath(CFG_AD_UPDATE_PATH + File.separator + fTPfilename);
//            long fileSize = (int) file.length();
//            int m = (int) (fileSize % 4);
//            long fileSize2 = fileSize + m;
//            LogUtils.v(fileSize2);
//            byte[] fileSizeBytes = ByteTool.long2bytes(fileSize2, 4);
//
//            byte[] fileBytes = FileIOUtils.readFile2BytesByStream(file);
//            byte[] fileBytes2 = FileIOUtils.readFile2BytesByStream(file);
//            if (m == 1) {
//                fileBytes2 = ArrayUtils.add(fileBytes, new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF});
//            } else if (m == 2) {
//                fileBytes2 = ArrayUtils.add(fileBytes, new byte[]{(byte) 0xFF, (byte) 0xFF});
//            } else if (m == 3) {
//                fileBytes2 = ArrayUtils.add(fileBytes, new byte[]{(byte) 0xFF});
//            }
//
//            int crc32Value = ByteTool.getCRC32(fileBytes2);
//            LogUtils.v(crc32Value);
//            LogUtils.v(ConvertUtils.int2HexString(crc32Value));
//            byte[] crc32ValueBytes = ByteTool.long2bytes((long) crc32Value, 4);
//
//            byte sum = (byte) (0x0C + 0x07 + (byte) 0x80 + 0x08 + fileSizeBytes[3] + fileSizeBytes[2] + fileSizeBytes[1] + fileSizeBytes[0]
//                    + crc32ValueBytes[3] + crc32ValueBytes[2] + crc32ValueBytes[1] + crc32ValueBytes[0]);
//
//            byte[] otuBytes = new byte[]{(byte) 0xA5, 0x5A, 0x0C, 0x00, 0x07
//                    , 0x00, (byte) 0x80, 0x00, 0x08
//                    , fileSizeBytes[3], fileSizeBytes[2], fileSizeBytes[1], fileSizeBytes[0]
//                    , crc32ValueBytes[3], crc32ValueBytes[2], crc32ValueBytes[1], crc32ValueBytes[0],
//                    sum, (byte) 0xAA, 0x55};
//            // 写入数据
//            try {
//                LogUtils.v("程序信息", ConvertUtils.bytes2HexString(otuBytes));
//                out.write(otuBytes);
//                out.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SystemClock.sleep(50);
//
//            long time = System.currentTimeMillis() + 5000;//本条命令时间如果短了（最小2s），读取不到返回的数据
//            int read_count = mInputStream.available();
//            while (read_count == 0) {
//                SystemClock.sleep(50);
//                read_count = mInputStream.available();
//                long currentTime = System.currentTimeMillis();
//                if (currentTime > time) {
//                    return;//超时--可能设备没有连接好
//                }
//            }
//            byte[] buffer = new byte[read_count];
//            mInputStream.read(buffer, 0, read_count);
//            LogUtils.v("程序信息返回", ConvertUtils.bytes2HexString(buffer));
//
//            if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x07) {  //验证码
//                if (buffer[5] == 0x00) {//成功
//                    updateFirmwareContent(fileBytes);
//                } else if (buffer[5] == 0x01) {//起始地址错误
//                    ToastUtils.showShort("起始地址错误");
//                    LogUtil.v("起始地址错误");
//                } else if (buffer[5] == 0x02) {//程序太长
//                    ToastUtils.showShort("程序太长");
//                    LogUtil.v("程序太长");
//                } else if (buffer[5] == 0x03) {//FLASH擦除失败
//                    ToastUtils.showShort("FLASH擦除失败，重启酒精测试仪，然后重启app");
//                    LogUtil.v("FLASH擦除失败，重启酒精测试仪，然后重启app");
//                }
//            } else if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x10) {
//                toastErrMsg(buffer, "程序信息错误");
//            }
//        } catch (Exception e) {
//            if (mSerialPort != null) {
//                mSerialPort.close();
//            }
//        }
//    }
//
//    int firmwareSendOffset = 0;//固件程序数据包偏移
//    int sendSize = 512;//每次发送的字节数
//
//    /**
//     * 程序内容
//     */
//    private void updateFirmwareContent(byte[] fileBytes) {
//        try {
//            SystemClock.sleep(50);
//            int fileLength = fileBytes.length;//文件的长度
//
//            byte[] sendBytes = new byte[sendSize];
//            for (int i = 0; i < sendSize; i++) {
//                sendBytes[i] = (byte) 0xFF;
//            }
//            if (fileLength > firmwareSendOffset) {
//                if ((fileLength - firmwareSendOffset) > 512) {
//                    System.arraycopy(fileBytes, firmwareSendOffset, sendBytes, 0, sendSize);//将文件二维码复制到要发送的数组中512位
//                } else {
//                    System.arraycopy(fileBytes, firmwareSendOffset, sendBytes, 0, fileLength - firmwareSendOffset);//将文件二维码复制到要发送的数组中
//                }
//            } else {
//                //不做处理，发送一次全FF
//            }
//
//
//            //校验求和
//            byte sum;
//            byte sendDataSum = 0x00;
//            for (byte sendByte : sendBytes) {
//                sendDataSum = (byte) (sendDataSum + sendByte);
//            }
//
//            byte[] offsetBytes = ByteTool.intToByteArray(firmwareSendOffset);//程序数据包偏移
//            byte[] sendSizeBytes = ByteTool.intToByteArray(sendSize);//数据包大小 0x00, 0x02
//            int dataLength = 6 + sendSize;
//            byte[] dataLengthBytes = ByteTool.intToByteArray(dataLength);//数据长度 0x06, 0x02
//            sum = (byte) (dataLengthBytes[3] + dataLengthBytes[2] + 0x17 + offsetBytes[3] + offsetBytes[2] + offsetBytes[1] + offsetBytes[0] + sendSizeBytes[3] + sendSizeBytes[2] + sendDataSum);
//            byte[] outBytes1 = new byte[]{(byte) 0xA5, 0x5A, dataLengthBytes[3], dataLengthBytes[2], 0x17
//                    , offsetBytes[3], offsetBytes[2], offsetBytes[1], offsetBytes[0],
//                    sendSizeBytes[3], sendSizeBytes[2]};//帧头(2byte)	数据长度(2byte)	命令码(1byte)	程序数据包偏移(4)	数据包大小(2)
//            byte[] outBytes2 = new byte[]{sum, (byte) 0xAA, 0x55};//校验(1byte)	帧尾(2byte)
//            byte[] outBytes = ByteTool.concatAll(outBytes1, sendBytes, outBytes2);
//
//            // 写入数据
//            try {
//                LogUtil.v("程序内容", ConvertUtils.bytes2HexString(outBytes));
//                out.write(outBytes);
//                out.flush();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            SystemClock.sleep(50);
//
//            long time = System.currentTimeMillis() + 2000;
//            int read_count = mInputStream.available();
//            while (read_count == 0) {
//                SystemClock.sleep(50);
//                read_count = mInputStream.available();
//                long currentTime = System.currentTimeMillis();
//                if (currentTime > time) {
//                    return;//超时--可能设备没有连接好
//                }
//            }
//            byte[] buffer = new byte[read_count];
//            mInputStream.read(buffer, 0, read_count);
//            LogUtil.v("程序内容返回", ConvertUtils.bytes2HexString(buffer));
//
//            if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x17) {  //验证码
//                if (buffer[5] == 0x00) {//成功
//                    if (firmwareSendOffset < fileLength) {
//                        firmwareSendOffset += sendSize;
//                        int precent = firmwareSendOffset * 100 / fileLength;
//                        if (precent > 100) {
//                            precent = 100;
//                        }
//                        LogUtil.v("刷包进度" + precent + "%");
//                        updateFirmwareContent(fileBytes);
//                    } else {
//                        firmwareSendOffset = 0;//可能因为是单例的原因，杀死程序后这个不置0，手动置0
//                        ToastUtils.showShort("酒测仪升级成功");
//                        LogUtils.v("酒测仪升级成功");
//                    }
//                } else if (buffer[5] == 0x01) {//失败
//                    ToastUtils.showShort("酒测仪升级：失败，请重启程序");
//                } else if (buffer[5] == 0x02) {//失败
//                    ToastUtils.showShort("酒测仪升级：程序CRC校验错误(仅限最后一包)，请重启程序");
//                }
//            } else if (buffer[0] == (byte) 0xA5 && buffer[1] == 0x5A       //开头
//                    && buffer[4] == 0x10) {
//                toastErrMsg(buffer, "程序内容错误");
//            }
//        } catch (Exception e) {
//            if (mSerialPort != null) {
//                mSerialPort.close();
//            }
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 当酒测仪判断协议格式错误,应答本条
//     *
//     * @param buffer 返回的应答
//     */
//    private void toastErrMsg(byte[] buffer, String name) {
//        if (buffer[5] == 0x01) {
//            ToastUtils.showShort(name + "——帧头错误");
//        } else if (buffer[5] == 0x02) {
//            ToastUtils.showShort(name + "——帧尾错误");
//        } else if (buffer[5] == 0x03) {
//            ToastUtils.showShort(name + "——校验错误");
//        } else if (buffer[5] == 0x04) {
//            ToastUtils.showShort(name + "——命令错误");
//        } else {
//            ToastUtils.showShort(name + "——未知错误");
//        }
//    }
//
//}
